// Object.defineProperty()
// http://t.csdn.cn/3NB8S
const obj1 = {};

Object.defineProperty(obj1, "property1", {
  value: 22,
  writable: false,
});

obj1.property1 = 33;

console.log(obj1.property1); // 22

let obj2 = {};
// 给对象添加一个设置了数据描述符的属性
Object.defineProperty(obj2, "aa", {
  value: 22,
  writable: true,
  enumerable: true,
  configurable: true,
});
console.log(obj2.aa); // 22

// 给对象添加一个设置了存取描述符的属性
let bbValue = 55;
Object.defineProperty(obj2, "bb", {
  get() {
    return bbValue;
  },
  set(newValue) {
    bbValue = newValue;
  },
  enumerable: true,
  configurable: true,
});
console.log(obj2.bb); // 55

// 修改属性
let obj3 = {};
// writable 是数据描述符的键值，当 writable 属性设置为 false 时，该属性不可写。即不能被重新赋值。默认为 false。
Object.defineProperty(obj3, "aa", {
  value: 22,
  writable: false,
});
obj3.aa = 33;
console.log(obj3.aa); // 22

let obj4 = { c: 3 };
// enumerable 定义了属性是否可以在 for...in 循环和 Object.keys() 中被枚举。默认为 false，不可枚举。
Object.defineProperty(obj4, "a", {
  value: 1,
  enumerable: true,
});
Object.defineProperty(obj4, "b", {
  value: 2,
  enumerable: false,
});
for (let i in obj4) {
  console.log(i);
}
// c
// a
console.log(Object.keys(obj4)); // [ 'c', 'a' ]

let obj5 = {};
// configurable 表示属性是否可以被删除，以及除 value 和 writable 外的其他特性是否可以被修改。默认为 false。
Object.defineProperty(obj5, "aa", {
  get() {
    return 1;
  },
  configurable: false,
});
Object.defineProperty(obj5, "aa", {
  configurable: true,
}); // 报错
Object.defineProperty(obj5, "aa", {
  enumerable: true,
}); // 报错
Object.defineProperty(obj5, "aa", {
  set() {},
}); // 报错
delete obj5.aa; // 报错

// 使用点运算符和 Object.defineProperty() 为对象的属性赋值时，数据描述符中的属性默认值不同
let obj6 = {};

// 点运算符为对象的属性赋值
obj6.aa = 22;
// 等同于
Object.defineProperty(obj6, "aa", {
  value: 22,
  writable: true,
  configurable: true,
  enumerable: true,
});
// Object.defineProperty() 为对象的属性赋值
Object.defineProperty(obj6, "bb", { value : 66 });
// 等同于：
Object.defineProperty(obj6, "bb", {
  value: 66,
  writable: false,
  configurable: false,
  enumerable: false
});

// ----------------------------------